package com.waijiaojun.tpo.service.baidu;

import com.waijiaojun.tpo.entity.baidu.BaiduAccessToken;
import com.waijiaojun.tpo.entity.baidu.BaiduAccessTokenLog;
import com.waijiaojun.tpo.entity.weixin.WeixinAccessToken;
import com.waijiaojun.tpo.entity.weixin.WeixinAccessTokenLog;
import com.waijiaojun.tpo.entity.weixin.WeixinPublic;
import com.waijiaojun.tpo.exception.ServerException;
import com.waijiaojun.tpo.repository.baidu.BaiduAccessTokenDao;
import com.waijiaojun.tpo.repository.baidu.BaiduAccessTokenLogDao;
import com.waijiaojun.tpo.repository.weixin.WeixinAccessTokenDao;
import com.waijiaojun.tpo.repository.weixin.WeixinAccessTokenLogDao;
import com.waijiaojun.tpo.rest.dto.ReceiveAccessTokenDto;
import com.waijiaojun.tpo.rest.dto.baidu.ReceiveBaiduAccessTokenDto;
import com.waijiaojun.tpo.service.weixin.WeixinPublicService;
import com.waijiaojun.tpo.utils.Constants;
import com.waijiaojun.tpo.utils.HttpUtil;
import com.waijiaojun.tpo.utils.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;

/**
 * @author Peter
 */
// Spring Service Bean的标识.
@Component
public class BaiduAccessTokenService {

    private static Logger logger = LoggerFactory.getLogger(BaiduAccessTokenService.class);

    @Autowired
    private BaiduAccessTokenDao baiduAccessTokenDao;

    @Autowired
    private BaiduAccessTokenLogDao baiduAccessTokenLogDao;

    public String getAccessToken() {
        BaiduAccessToken baiduAccessToken = baiduAccessTokenDao.getByWeixinPublicId(Constants.publicId);
        if (baiduAccessToken == null) {
            // 数据库中没有AccessToken信息，从百度服务器获取AccessToken
            ReceiveBaiduAccessTokenDto dto = receiveAccessToken();
            baiduAccessToken = dtoToEntity(dto);
            BaiduAccessTokenLog log = dtoToEntityLog(dto);

            baiduAccessTokenDao.save(baiduAccessToken);
            baiduAccessTokenLogDao.save(log);
        } else {
            // 判断是否过期
            if (isExpires(baiduAccessToken)) {
                //过期，重新获取
                Long id = baiduAccessToken.getId();
                ReceiveBaiduAccessTokenDto dto = receiveAccessToken();
                baiduAccessToken = dtoToEntity(dto);
                baiduAccessToken.setId(id);
                BaiduAccessTokenLog log = dtoToEntityLog(dto);
                baiduAccessTokenDao.update(baiduAccessToken);
                baiduAccessTokenLogDao.save(log);
            }
        }
        return baiduAccessToken.getAccessToken();
    }

    // 获取access_token
    public ReceiveBaiduAccessTokenDto receiveAccessToken() {
        String url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + Constants.baiduApiKey + "&client_secret=" + Constants.baiduApiSecretKey;

        String body = HttpUtil.httpGet(url);
        ReceiveBaiduAccessTokenDto bean = null;
        try {
            bean = JsonUtil.toObject(body, ReceiveBaiduAccessTokenDto.class);
        } catch (IOException e) {
            throw new ServerException("获取access_token失败：从百度服务器读取数据失败");
        }
        return bean;
    }

    private BaiduAccessToken dtoToEntity(ReceiveBaiduAccessTokenDto dto) {
        BaiduAccessToken token = new BaiduAccessToken();
        token.setAccessToken(dto.getAccess_token());
        token.setCreateDate(new Date());
        token.setExpiresIn(dto.getExpires_in());
        token.setUpdateDate(new Date());
        token.setWeixinPublicId(Constants.publicId);
        return token;
    }

    private BaiduAccessTokenLog dtoToEntityLog(ReceiveBaiduAccessTokenDto dto) {
        BaiduAccessTokenLog tokenLog = new BaiduAccessTokenLog();
        tokenLog.setAccessToken(dto.getAccess_token());
        tokenLog.setExpiresIn(dto.getExpires_in());
        tokenLog.setCreateDate(new Date());
        tokenLog.setWeixinPublicId(Constants.publicId);
        return tokenLog;
    }

    /**
     * 是否过期
     *
     * @return boolean true:过期，false:未过期
     */
    public boolean isExpires(BaiduAccessToken token) {
        boolean isExpires = false;
        Calendar sendedCal = Calendar.getInstance();//
        sendedCal.setTime(token.getUpdateDate());
        sendedCal.add(Calendar.SECOND, token.getExpiresIn().intValue() - 20);//提前20秒过期
        Calendar nowCal = Calendar.getInstance();
        nowCal.setTime(new Date());

        if (sendedCal.before(nowCal)) {
            isExpires = true;
        }
        return isExpires;
    }

}
